﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YJKSparseDistance;
using YJKSparseDistance.ModelLayer;
using YJKSparseDisOfRoom.ModelLayer;
using YJKSparseDisOfRoom.Properties;

namespace YJKSparseDisOfRoom.ControlLayer
{
	internal class CalculateManger
	{
		public List<AreaCheckResultPacker> LstCalculateResult
		{
			get
			{
				return this.m_lstCalculateResult;
			}
			private set
			{
				this.m_lstCalculateResult = value;
			}
		}

		internal CalculateManger(List<RoomPacker_EvacuationDistance> inputRoots, RulePacker inputRule)
		{
			foreach (RoomPacker_EvacuationDistance inputPacker in inputRoots)
			{
				this.m_lstAllInputRoot.Add(RoomNodePacker.GetARoomNode(inputPacker));
			}
			this.m_useRule = inputRule;
		}

		internal void Calculate()
		{
			foreach (RoomNodePacker roomNodePacker in this.m_lstAllInputRoot)
			{
				roomNodePacker.CalculateConditionEnum = NodeConditionEnum.IsRunWay;
			}
			List<RoomNodePacker> list = this.m_lstAllInputRoot;
			while (list.Count != 0)
			{
				list = this.GetNextLayerRoom(list);
				this.CalculateListNode(list);
				foreach (RoomNodePacker roomNodePacker2 in list)
				{
					this.m_lstAllCalculateResultBean.AddRange(roomNodePacker2.LstAllResults);
				}
			}
			foreach (ResultBean_InRoom resultBean_InRoom in this.m_lstAllCalculateResultBean)
			{
				resultBean_InRoom.UseRule = this.m_useRule;
			}
			this.OrderResults();
		}

		private void OrderResults()
		{
			IEnumerable<IGrouping<int, ResultBean_InRoom>> enumerable = from n in this.m_lstAllCalculateResultBean
			where n.StartPoint is EndPointPacker_InRoom && !(n.StartPoint.UseElementPacker is DoorPacker_EvacuationDistance) && (n.StartPoint as EndPointPacker_InRoom).ThisArea != null && !n.IfRight && n.EndPoint.ThisRoom != null
			select n into k
			group k by (k.StartPoint as EndPointPacker_InRoom).ThisArea.Id.IntegerValue;
			List<List<ResultBean>> list = new List<List<ResultBean>>();
			List<ResultBean> list2 = new List<ResultBean>();
			List<ResultBean> list3 = new List<ResultBean>();
			foreach (IGrouping<int, ResultBean_InRoom> grouping in enumerable)
			{
				Area inputArea = TempleCmd.UseDoc.GetElement(new ElementId(grouping.Key)) as Area;
				list = new List<List<ResultBean>>();
				foreach (IEnumerable<ResultBean_InRoom> source in from k in grouping
				group k by k.EndPoint.ThisRoom.Id.IntegerValue)
				{
					list2 = new List<ResultBean>();
					list3 = new List<ResultBean>();
					foreach (IGrouping<EndPointPacker, ResultBean_InRoom> grouping2 in source.GroupBy((ResultBean_InRoom k) => k.StartPoint))
					{
						foreach (ResultBean_InRoom resultBean_InRoom in grouping2)
						{
                            if (!YJKSparseDistance.Utility.IfResultBeanTrusted(inputArea, resultBean_InRoom, Resources.str_UseGuid))
							{
								list2.Add(resultBean_InRoom);
							}
						}
					}
					if (list2.Count > 0)
					{
						list3.Add(list2.OrderBy((ResultBean k) => k.Distance).ElementAt(0));
					}
				}
				if (list3.Count > 0)
				{
					List<List<ResultBean>> list4 = list;
					List<ResultBean> list5 = new List<ResultBean>();
					list5.Add((from k in list3
					orderby -k.Distance
					select k).ElementAt(0));
					list4.Add(list5);
				}
				this.m_lstCalculateResult.Add(new AreaCheckResultPacker(inputArea, list));
			}
		}

		private List<RoomNodePacker> GetNextLayerRoom(List<RoomNodePacker> input)
		{
			return this.m_useRoomGeter.GetPrepareCalculeNodes(input);
		}

		private void CalculateListNode(List<RoomNodePacker> input)
		{
			foreach (RoomNodePacker inputPacker in input)
			{
				this.m_useCalculater.CalculateRoomNodePacker(inputPacker);
			}
		}

		private List<AreaCheckResultPacker> m_lstCalculateResult = new List<AreaCheckResultPacker>();

		private List<ResultBean_InRoom> m_lstAllCalculateResultBean = new List<ResultBean_InRoom>();

		private RoomBFSGeter m_useRoomGeter = new RoomBFSGeter();

		private BaseInRoomCalculater m_useCalculater = new BaseInRoomCalculater();

		private List<RoomNodePacker> m_lstAllInputRoot = new List<RoomNodePacker>();

		private RulePacker m_useRule;
	}
}
